//+------------------------------------------------------------------+
//|                                             SignalBullsPower.mqh |
//|                             Copyright 2000-2025, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert/ExpertSignal.h>    // 专家顾问信号基类（提供信号生成框架）

// wizard description start（MQL5 策略向导描述，用于识别类信息与参数）
//+------------------------------------------------------------------+
//| 类功能描述                                                       |
//| Title=基于牛市力量振荡器（Bulls Power）的交易信号                 |
//| Type=SignalAdvanced                                              |
//| Name=Bulls Power                                                 |
//| ShortName=BullsPower                                             |
//| Class=CSignalBullsPower                                          |
//| Page=signal_bulls                                                |
//| Parameter=PeriodBulls,int,13,计算周期（Bulls Power 指标核心周期）  |
//+------------------------------------------------------------------+
// wizard description end

//+------------------------------------------------------------------+
//| CSignalBullsPower 类：基于牛市力量振荡器的交易信号生成器           |
//| 核心能力：继承自 CExpertSignal，通过调用 Bulls Power 指标（反映“牛市力量”的动量指标）， |
//|           识别两类看跌信号（指标转向、指标与价格背离），仅生成空单信号（无多单逻辑）， |
//|           支持通过“信号权重”调整不同形态的优先级，适配牛市末期的空头反转行情       |
//| 核心逻辑：Bulls Power = 最高价 - 对应周期的 EMA（通常为收盘价EMA），值>0表示牛市力量占优， |
//|           值越大牛市越强；通过“指标从向上转为向下”“价格创新高但指标不创新高”判断看跌信号 |
//| 适用场景：牛市末期的止盈/做空交易（Bulls Power 擅长识别多头力量衰竭），适合外汇、期货等 |
//|           品种，需与趋势指标（如均线、MACD）配合使用，避免在强牛市中过早入场做空    |
//+------------------------------------------------------------------+
class CSignalBullsPower : public CExpertSignal
  {
protected:
   // 核心组件与参数（保护，子类可访问）
   CiBullsPower      m_bulls;          // Bulls Power 指标对象（封装指标计算与数据读取）
   // 指标可调参数（与指标原生参数对应，默认周期兼顾灵敏度与稳定性）
   int               m_period_bulls;   // 计算周期（Bulls Power 核心周期，默认13，值越大信号越平滑）
   // 市场形态信号权重（0-100，值越大信号优先级越高，默认配置突出背离信号）
   int               m_pattern_0;      // 形态0权重：指标向预期方向转向（牛市力量减弱，指标从向上转向下）
   int               m_pattern_1;      // 形态1权重：指标与价格背离（价格创新高，Bulls Power 不创新高，多头衰竭）
   // 极值分析辅助变量（用于背离信号判断，存储指标与价格的极值关系）
   double            m_extr_osc[10];   // Bulls Power 指标极值数组（存储最近10个指标极值点）
   double            m_extr_pr[10];    // 对应价格极值数组（存储指标极值点对应的价格极值）
   int               m_extr_pos[10];   // 极值位置数组（存储极值点对应的K线偏移量，单位：根）
   uint              m_extr_map;       // 极值关系位图（用二进制位记录指标与价格极值的相对关系，辅助背离判断）

public:
   //----------------------------------------------------------------
   // 构造与析构函数
   //----------------------------------------------------------------
   /**
    * @brief 构造函数：初始化 Bulls Power 信号生成器
    * @details 1. 初始化 Bulls Power 指标对象及默认参数（计算周期=13）；
    *          2. 设置默认信号权重（形态0=20，形态1=80，突出背离信号的重要性）；
    *          3. 启用价格序列（最高价+最低价，因指标计算依赖最高价与EMA的差值）；
    *          4. 初始化极值分析数组（指标极值、价格极值、位置）及位图；
    *          5. 继承父类 CExpertSignal 的信号框架初始化
    */
                     CSignalBullsPower(void);

   /**
    * @brief 析构函数：清理 Bulls Power 信号生成器资源
    * @details 释放指标对象及极值数组占用的内存，依赖父类析构逻辑完成信号框架资源清理
    */
                    ~CSignalBullsPower(void);

   //----------------------------------------------------------------
   // 指标参数配置：修改 Bulls Power 计算周期（外部调用接口）
   //----------------------------------------------------------------
   /**
    * @brief 设置 Bulls Power 指标的计算周期
    * @param value [in] 周期值（需>0，建议10-20，值越大指标越平滑，信号滞后性越强）
    * @note 周期决定指标对价格变化的反应速度，13为默认值，适合中短线交易
    */
   void              PeriodBulls(int value);

   //----------------------------------------------------------------
   // 信号权重配置：修改不同市场形态的信号强度（外部调用接口）
   //----------------------------------------------------------------
   /**
    * @brief 设置形态0（指标转向）的信号权重
    * @param value [in] 权重值（0-100，建议10-30，值越大越重视指标短期转向信号）
    */
   void              Pattern_0(int value);

   /**
    * @brief 设置形态1（指标-价格背离）的信号权重
    * @param value [in] 权重值（0-100，建议70-90，值越大越重视多头衰竭的背离信号）
    */
   void              Pattern_1(int value);

   //----------------------------------------------------------------
   // 参数验证：确保指标参数与信号配置有效（信号生成前提）
   //----------------------------------------------------------------
   /**
    * @brief 验证 Bulls Power 指标参数与信号配置的有效性
    * @return bool - 验证结果：true=所有参数有效，false=存在无效参数（如周期≤0）
    * @note 验证逻辑：
    *       1. 先调用父类 ValidationSettings() 验证信号框架基础参数（如品种、周期）；
    *       2. 额外验证指标计算周期（m_period_bulls）是否>0，若无效则输出错误日志并返回false；
    *       3. 确保指标参数符合交易规则，避免因参数错误导致指标计算失败
    */
   virtual bool      ValidationSettings(void);

   //----------------------------------------------------------------
   // 指标初始化：创建并注册 Bulls Power 指标（信号生成的前提）
   //----------------------------------------------------------------
   /**
    * @brief 初始化 Bulls Power 指标及信号所需的价格序列数据
    * @param indicators [in] 指标集合对象（用于管理所有策略用到的指标，如 Bulls Power、均线等）
    * @return bool - 初始化结果：true=成功（指标创建+注册到指标集合），false=失败
    * @note 调用流程：
    *       1. 先调用父类 InitIndicators() 完成基础信号框架与价格序列初始化；
    *       2. 调用内部 InitBears() 方法创建指标（注：原代码方法名疑似笔误，实际初始化 Bulls Power），
    *          绑定当前品种、周期及计算周期；
    *       3. 若指标创建失败（如参数无效、品种不支持），返回 false 并终止信号生成
    */
   virtual bool      InitIndicators(CIndicators *indicators);

   //----------------------------------------------------------------
   // 信号判断核心方法：仅生成空单（卖出）信号（无多单逻辑）
   //----------------------------------------------------------------
   /**
    * @brief 判断当前市场是否满足空单（卖出）开仓条件，返回信号权重
    * @return int - 空单信号权重（0-100，0=无信号，值越大信号越强烈）
    * @note 核心判断逻辑（基于 Bulls Power 指标特性）：
    *       1. 基础过滤：仅当指标值>0（牛市力量占优）时才可能生成看跌信号，否则返回0；
    *       2. 形态0（指标转向）：若指标从向上趋势转为向下（StateBulls(idx)<0），返回形态0权重；
    *       3. 形态1（背离信号）：调用 ExtStateBulls() 分析极值，若价格创新高但指标不创新高（多头衰竭），
    *          返回形态1权重（优先级高于形态0）；
    *       4. 仅生成空单信号，因 Bulls Power 本质是“衡量多头力量”，仅适用于判断空头反转
    */
   virtual int       ShortCondition(void);

   //----------------------------------------------------------------
   // 多单信号方法：此类不实现多单逻辑（Bulls Power 不适合判断多头信号）
   //----------------------------------------------------------------
   /**
    * @brief 多单（买入）信号判断（未实现）
    * @return int - 始终返回0（无多单信号）
    * @note 设计说明：Bulls Power 指标核心作用是“识别多头力量强弱”，仅能有效判断“多头衰竭”的空单信号，
    *       无法可靠识别多头启动信号，因此不实现此方法，策略需通过其他指标（如 Bears Power）获取多单信号
    */
   virtual int       LongCondition(void) { return 0; }

protected:
   //----------------------------------------------------------------
   // 内部辅助方法：Bulls Power 指标初始化（仅内部调用，原代码方法名疑似笔误）
   //----------------------------------------------------------------
   /**
    * @brief 创建并初始化 Bulls Power 指标（绑定品种、周期、参数，注册到指标集合）
    * @param indicators [in] 指标集合对象（用于管理 Bulls Power 指标）
    * @return bool - 初始化结果：true=成功（指标创建+参数配置完成），false=失败
    * @note 内部流程：
    *       1. 检查指标集合指针有效性；
    *       2. 将指标对象（m_bulls）添加到指标集合；
    *       3. 调用 m_bulls.Create() 绑定当前交易品种、周期及计算周期（m_period_bulls）；
    *       4. 原代码方法名“InitBears”为疑似笔误，实际功能为初始化 Bulls Power 指标；
    *       5. 若添加或创建失败，输出错误日志并返回 false
    */
   bool              InitBears(CIndicators *indicators);

   //----------------------------------------------------------------
   // 数据读取与状态分析：快捷获取指标数据及判断状态（保护，子类可直接调用）
   //----------------------------------------------------------------
   /**
    * @brief 获取指定索引的 Bulls Power 指标值
    * @param ind [in] 索引（0=当前K线，1=前一根K线，以此类推）
    * @return double - 指标值（>0=牛市力量占优，值越大多头越强；<0=熊市力量占优）
    */
   double            Bulls(int ind);

   /**
    * @brief 计算指定索引K线的 Bulls Power 指标差值（当前K线 - 前一根K线，反映指标趋势变化）
    * @param ind [in] 索引（0=当前K线，1=前一根K线，以此类推）
    * @return double - 差值（>0=指标向上（多头力量增强），<0=指标向下（多头力量减弱））
    */
   double            DiffBulls(int ind);

   /**
    * @brief 分析指定索引K线的 Bulls Power 指标趋势状态（连续同方向变化的K线数量）
    * @param ind [in] 索引（分析起点K线）
    * @return int - 趋势状态值（正数=连续向上变化的K线数，负数=连续向下变化的K线数，0=无连续趋势）
    * @note 例如返回 -2 表示从 ind 开始连续2根K线指标向下（多头力量持续减弱），用于判断指标转向
    */
   int               StateBulls(int ind);

   /**
    * @brief 扩展分析 Bulls Power 与价格的极值关系（生成背离判断所需的极值位图）
    * @param ind [in] 索引（分析起点K线）
    * @return bool - 分析结果：true=成功（生成极值数组与位图），false=失败（数据不足）
    * @note 核心逻辑：
    *       1. 从 ind 开始遍历K线，通过 StateBulls() 识别指标的极值点（连续同方向变化的转折点）；
    *       2. 记录每个指标极值点对应的价格极值（指标高点对应价格高点，因指标与最高价强相关）；
    *       3. 用 m_extr_map 位图记录相邻极值点的关系（如价格创新高但指标未创新高 → 标记为顶背离）；
    *       4. 结果用于形态1（背离信号）的判断，是此类最核心的分析逻辑
    */
   bool              ExtStateBulls(int ind);
  };
//+------------------------------------------------------------------+